home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / ALLOC.C < prev    next >
C/C++ Source or Header  |  1990-08-03  |  8KB  |  389 lines

  1. /* memory allocation routines
  2.  *
  3.  * Adapted from alloc routine in K&R; memory statistics and interrupt
  4.  * protection added for use with net package.
  5.  */
  6.  
  7. #include <stdio.h>
  8.  
  9. #if (defined(MSC) || defined(__TURBOC__))
  10. # include <alloc.h>
  11. #else
  12. # ifdef M_XENIX
  13. #  include <prototypes.h>
  14. # else
  15. extern char *sbrk();
  16. extern int brk();
  17. # endif
  18. #endif
  19.  
  20. #include "global.h"
  21. #include "alloc.h"
  22.  
  23. static long grabbedbytes = 0;
  24. static unsigned memfail = 0;
  25. static HEADER base = {&base,1};
  26. HEADER PTR allocp = &base;
  27. int need_disable = 0;
  28.  
  29. /* Define ALLOCDEBUG for allocation recording. Note: works only with
  30.  * small memory model
  31.  */
  32. #ifdef    ALLOCDEBUG
  33. #define NALLOC    150
  34. /* Map of allocated memory chunks */
  35. struct alloc {
  36.     char *addr;
  37.     unsigned size;
  38.     long pc;
  39. };
  40. struct alloc alloc[NALLOC];
  41. #endif
  42.  
  43. /* Allocate block of 'nb' bytes */
  44. #ifdef MSDOS
  45. void *
  46. #else
  47. char *
  48. #endif
  49. malloc(nb)
  50. unsigned nb;
  51. {
  52.     HEADER PTR morecore();
  53.     register HEADER PTR p, PTR q;
  54.     register unsigned nu;
  55. #ifdef    ALLOCDEBUG
  56.     struct alloc *ap;
  57.     unsigned short *ptr;
  58. #endif
  59. #ifndef NODISABLE
  60.     char i_state;
  61.     
  62.     if (need_disable)
  63.         i_state = disable();
  64. #endif
  65.     /* Round up to full block, incl hdr */
  66.     nu = (nb + 2 * sizeof(HEADER) - 1) / sizeof(HEADER);
  67.     if ((q = allocp) == NULLHDR){
  68.         base.s.ptr = allocp = q = &base;
  69.         base.s.size = 1;
  70.     }
  71.     for (p = q->s.ptr; ; q = p, p = p->s.ptr){
  72.         if (p->s.size >= nu){
  73.             /* This chunk is at least as large as we need */
  74.             if (p->s.size == nu){
  75.                 /* Perfect fit; remove from list */
  76.                 q->s.ptr = p->s.ptr;
  77.             } else {
  78.                 /* Carve out piece from end of entry */
  79.                 p->s.size -= nu;
  80.                 p += p->s.size;
  81.                 p->s.size = nu;
  82.             }
  83.             allocp = q;
  84.             p->s.ptr = p;    /* for auditing */
  85. #ifdef    ALLOCDEBUG
  86.             for(ap = alloc;ap < &alloc[NALLOC];ap++){
  87.                 if(ap->addr == NULLCHAR){
  88.                     ap->addr = (char *)(p+1);
  89.                     ap->size = nb;
  90.                     ptr = &nb;
  91. #ifdef    LARGECODE
  92.                     ap->pc = (long)ptr[-1] << 16 +
  93.                         (long)ptr[-2];
  94. #else
  95.                     ap->pc = (long)ptr[-1];
  96. #endif
  97.                     break;
  98.                 }
  99.             }
  100. #endif
  101. #ifndef NODISABLE
  102.             if (need_disable)
  103.                 restore(i_state);
  104. #endif
  105.             return (char *)(p + 1);
  106.         }
  107.         if (p == allocp && (p = morecore(nu)) == NULLHDR){
  108.             memfail++;
  109. #ifndef NODISABLE
  110.             if (need_disable)
  111.                 restore(i_state);
  112. #endif
  113.             return NULLCHAR;
  114.         }
  115.     }
  116. }
  117.  
  118. /* Put memory block back on heap */
  119. void
  120. free(blk)
  121. #ifdef MSDOS
  122. void *blk;
  123. #else
  124. char *blk;
  125. #endif
  126. {
  127.     register HEADER PTR p, PTR q;
  128.     unsigned short *ptr;
  129. #ifdef    ALLOCDEBUG
  130.     struct alloc *ap;
  131. #endif
  132. #ifndef NODISABLE
  133.     char i_state;
  134. #endif
  135.  
  136.     if (blk == NULL)
  137.         return;
  138.  
  139. #ifndef NODISABLE
  140.     if (need_disable)
  141.         i_state = disable();
  142. #endif
  143.  
  144. #ifdef    ALLOCDEBUG
  145.     for(ap = alloc;ap < &alloc[NALLOC];ap++){
  146.         if(ap->addr == blk){
  147.             ap->addr = NULLCHAR;
  148.             break;
  149.         }
  150.     }
  151. #endif
  152.     p = (HEADER PTR)blk - 1;
  153.     /* Audit check */
  154.     if(p->s.ptr != p){
  155.         ptr = (unsigned short *)&blk;
  156.         printf("WARNING!! freeing garbage (0x%lx) pc = 0x%04x %04x\n",
  157.             ptr2long(blk),ptr[-1],ptr[-2]);
  158.         fflush(stdout);
  159. #ifndef NODISABLE
  160.         if (need_disable)
  161.             restore(i_state);
  162. #endif
  163. #ifdef    Z80
  164.         printf("SP = 0x%04x\n",getsp());
  165.         for(;;) ;
  166. #else
  167.         return;
  168. #endif
  169.     }
  170.     /* Search the free list looking for the right place to insert */
  171.     for(q = allocp; !(p > q && p < q->s.ptr); q = q->s.ptr){
  172.         /* Highest address on circular list? */
  173.         if(q >= q->s.ptr && (p > q || p < q->s.ptr))
  174.             break;
  175.     }
  176.     if(p + p->s.size == q->s.ptr){
  177.         /* Combine with front of this entry */
  178.         p->s.size += q->s.ptr->s.size;
  179.         p->s.ptr = q->s.ptr->s.ptr;
  180.     } else {
  181.         /* Link to front of this entry */
  182.         p->s.ptr = q->s.ptr;
  183.     }
  184.     if(q + q->s.size == p){
  185.         /* Combine with end of this entry */
  186.         q->s.size += p->s.size;
  187.         q->s.ptr = p->s.ptr;
  188.     } else {
  189.         /* Link to end of this entry */
  190.         q->s.ptr = p;
  191.     }
  192.     allocp = q;
  193. #ifndef NODISABLE
  194.     if (need_disable)
  195.         restore(i_state);
  196. #endif
  197. }
  198.  
  199. /* Move existing block to new area */
  200. #ifdef MSDOS
  201. void *
  202. #else
  203. char *
  204. #endif
  205. realloc(area,size)
  206. #ifdef MSDOS
  207. void *area;
  208. #else
  209. char *area;
  210. #endif
  211. unsigned size;
  212. {
  213.     unsigned osize;
  214.     HEADER PTR hp;
  215.     char *cp;
  216. #ifndef NODISABLE
  217.     /* Make sure nobody else comes in and takes it */
  218.     char i_state;
  219.     
  220.     if (need_disable)
  221.         i_state = disable();
  222. #endif
  223.  
  224.     hp = (HEADER PTR)area - 1;
  225.     osize = (hp->s.size -1) * sizeof(HEADER);
  226.  
  227.     free(area);
  228.     if((cp = malloc(size)) != NULLCHAR && cp != area)
  229.         memcpy((char *)cp,(char *)area,size>osize? osize : size);
  230. #ifndef NODISABLE
  231.     if (need_disable)
  232.         restore(i_state);
  233. #endif
  234.     return cp;
  235. }
  236.  
  237. /* Allocate block of cleared memory */
  238. #ifdef MSDOS
  239. void *
  240. #else
  241. char *
  242. #endif
  243. calloc(nelem,size)
  244. unsigned nelem; /* Number of elements */
  245. unsigned size;    /* Size of each element */
  246. {
  247.     register unsigned i;
  248.     register char *cp;
  249. #ifdef    ALLOCDEBUG
  250.     struct alloc *ap;
  251.     short *ptr;
  252. #endif
  253.     i = nelem * size;
  254.     if((cp = malloc(i)) != NULLCHAR)
  255.         memset(cp,0,i);
  256. #ifdef    ALLOCDEBUG
  257.     if(cp == NULLCHAR)
  258.         return cp;
  259.     /* Adjust caller field to indicate real caller, not calloc() */
  260.     ptr = (short *)&nelem;
  261.     for(ap = alloc; ap < &alloc[NALLOC];ap++)
  262.         if(ap->addr == cp)
  263.             ap->pc = (long)ptr[-1];
  264. #endif
  265.     return cp;
  266. }
  267.  
  268. /* Get more memory from the system and put it on the heap */
  269. HEADER PTR
  270. morecore(nu)
  271. unsigned nu;
  272. {
  273.     register char *cp;
  274.     register HEADER PTR up;
  275.  
  276.     /* adjust requests for small amounts upward to MIN_ALLOC */
  277.     /* when LARGEDATA, make sure we have one unit extra */
  278.     if (nu < (MIN_ALLOC / sizeof(HEADER)))
  279.         nu = MIN_ALLOC / sizeof(HEADER)
  280. #ifdef    LARGEDATA
  281.         + 1;
  282.     else
  283.         nu++
  284. #endif
  285.         ;
  286.     if ((int)(cp = sbrk(nu * sizeof(HEADER))) == -1)
  287.         return NULLHDR;
  288.     grabbedbytes += nu * sizeof(HEADER);
  289. #ifdef    LARGEDATA
  290.     /* most C runtimes don't like pointers with offset 0! */
  291.     if ((FP_OFF(cp) % sizeof(HEADER)) == 0){
  292.         cp += 4;        /* so move it off the para mark */
  293.         nu--;            /* which costs us one unit */
  294.     }
  295. #endif
  296.     up = (HEADER PTR)cp;
  297.     up->s.size = nu;
  298.     up->s.ptr = up; /* satisfy audit */
  299.     free((char *)(up + 1));
  300.     return allocp;
  301. }
  302.  
  303. /* Grab as much memory as possible from the system and put it on the heap */
  304. void
  305. grabcore()
  306. {
  307.     char *cp;
  308.     register HEADER PTR up;
  309.     register unsigned long size;
  310. #if (defined(MSC) || defined(__TURBOC__))
  311.     char redzone[4096];
  312. #endif
  313.  
  314.     /* Find out where the break is */
  315.     cp = sbrk(0);
  316.     /* Now try to push it as high as possible */
  317. #if (defined(MSC) || defined(__TURBOC__))
  318.     redzone[0] = size = 0;
  319.     while(sbrk(256) != (char *)(-1)) {
  320.         size += 256;
  321. # ifdef LARGEDATA
  322.         if (size > 32000)
  323.             break;
  324. # endif
  325.     }
  326. #else
  327.     for(size=256; size < 65535-256;size += 256){
  328.         if(brk((char *) (cp + size)) == -1){
  329.             size -= 256;
  330.             break;
  331.         }
  332.     }
  333. #endif
  334.     grabbedbytes += size;
  335. #ifdef    LARGEDATA
  336.     /* most C runtimes don't like pointers with offset 0! */
  337.     if ((FP_OFF(cp) % sizeof(HEADER)) == 0){
  338.         cp += 4;        /* so move it off the para mark */
  339.         size -= 4;
  340.     }
  341. #endif
  342.     up = (HEADER PTR)cp;
  343.     up->s.size = size / sizeof(HEADER);
  344.     up->s.ptr = up; /* satisfy audit */
  345.     free((char *)(up + 1));
  346. }
  347.  
  348. #ifndef NOMEMSTAT
  349. /* Print free list map */
  350. memstat(argc,argv)
  351. int argc;
  352. char *argv[];
  353. {
  354.     HEADER PTR p;
  355.     unsigned long totalfree;
  356.  
  357.     totalfree = 0;
  358.     p = &base;
  359.     do {
  360.         totalfree += (unsigned long) p->s.size * sizeof(HEADER);
  361.         if (argc != 1){
  362.             printf("%*lx %lu",2*sizeof(p),ptr2long(p),
  363.                 (unsigned long) p->s.size * sizeof(HEADER));
  364.             if(p == allocp)
  365.                 printf(" <-- allocp\n");
  366.             else
  367.                 printf("\n");
  368.         }
  369.         p = p->s.ptr;
  370.     } while(p != &base);
  371.     printf("Total: %lu bytes grabbed, %lu bytes free\n",
  372.         grabbedbytes,totalfree);
  373. #ifdef    ALLOCDEBUG
  374.     if (argc != 1) {
  375.         struct alloc *ap;
  376.         printf("addr      size      caller\n");
  377.         for(ap = alloc;ap < &alloc[NALLOC];ap++){
  378.             if(ap->addr != NULLCHAR)
  379.                 printf("0x%-8lx%-10d  %08lx\n",
  380.                     ptr2long(ap->addr),ap->size,ap->pc);
  381.         }
  382.     }
  383. #endif
  384.     printf("malloc fails %u\n",memfail);
  385.     fflush(stdout);
  386.     return 0;
  387. }
  388. #endif
  389.